//
//  main.m
//  C04_ 数组
//
//  Created by dllo on 15/11/20.
//  Copyright © 2015年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
    /** 定义宏 */
#define PI 3.1415

/** 带参数的宏 */
#define MUL(A, B) ((A) * (B)) /**< 计算两个数的积的宏 */



int main(int argc, const char * argv[]) {
#pragma mark - 知识点1 一维数组
    {
#if 0
        /** 定义一个数组 */
        int array[5] = {3, 5, 4, 6, 8};
        /** 
         * array: 数组名
         * int []: 数组类型
         * int: 数组中的元素类型
         * 5: 元素个数
         */
        
        /** 1.整型数组(数组元素都是整型) */
        int array2[5] = {3, 4};
        
        /** 2.浮点型数组(数组元素都是浮点型) */
        int array3[5] = {4.4, 3.14};
        
        /** 3.字符型数组(数组元素都是字符型) */
        char array4[5] = {'a', 'b'};
        
        /** 4.指针数组(数组元素都是指针) */
#endif
        /** 数组元素的访问 
         * 通过下标的形式:array[下标]
         * 下标是从0开始的
         */
#if 0
        int array5[5] = {4, 5, 6, 3, 5};
        printf("%d\n",array5[0]);
        printf("%d\n",array5[1]);
        printf("%d\n",array5[2]);
        
        /** 数组元素赋值 */
        array5[0] = 100;
        printf("%d\n",array5[0]);
        
        /** 使用for循环遍历数组(打印每个元素) */
        for (int i = 0; i < 5; i++) {
            printf("%d ",array5[i]);
        }
        printf("\n");
#endif
    }
#pragma mark ** 练习
    {
#if 0
        /** 1.输入5个数, 计算找出最大值和所有元素的和 */
        int array[5] = {0};
        int sum = 0;
        int max = 0;
        printf("请输入五个整数:");
        /** 遍历数组,输入 */
        for (int i = 0; i < 5; i++) {
            scanf("%d", &array[i]);
        
        /** 遍历数组,找出最大值和计算所有元素的和 */
            sum = sum + array[i];
            
            max = max > array[i] ? max : array[i];
            
        }
        printf("所有元素的和为:%d\n",sum);
        printf("最大值为:%d\n",max);
#endif
#if 0
        /** 2. 定义一个具有 20个元素 的 整型数组，每个元素的 取值范围是30-70之间，求 数组元素的和 */
        int array[20] = {0};
        int sum = 0;
        for (int i = 0; i < 20; i++) {
            array[i] = arc4random() % (70 - 30 + 1) + 30;
            sum = sum + array[i];
        }
        printf("数组元素的和为:%d\n",sum);
#endif
#if 0
        /**   3.复制一个数组，即两个数组 容量一样，把其中一个数组中的元素 复制 到另外一个数组中 */
        int array1[5] = {5, 2, 3, 4, 5};
        int array2[5] = {0};
        for (int i = 0; i < 5; i++) {
            array2[i] = array1[i];
            printf("%d ", array2[i]);
        }
      printf("\n");
#endif
#if 0
        /** 4.整形数组的长度20,随机数范围35 - 90, 找到数组中最大的元素的值和它所对应的下标 */
        int array[20] = {0};
        int max = 0;
        int index = 0;
        for (int i = 0; i < 20; i++) {
            array[i] = arc4random() % (90 - 35 + 1) + 35;
        }
        
        /** 遍历数组,找出最大值和它的下标 */
        for (int i = 0; i < 20; i++) {
            if (max < array[i]) {
                max = array[i];
                index = i;
            }
        }
        printf("max = %d\nindex = %d\n", max, index);
        
#endif
    }
#pragma mark - 知识点2 数组排序(冒泡排序)
    {
        /**
         *（1）、定义一个6个整型的数组，让奇偶位元素的值交换。
         *（2）、定义一个6个整型的数组，如果奇位比偶位元素的值大，则交换两个数的值。
         *（3）、定义一个6个整型的数组，通过俩俩比较把最大值放在后面，实现最大值放在最后。
         *（4）、在上题的基础上把倒数第二大的数字放在倒数第二位。（别再原来的for循环上操作，新创建一个for循环）
         *（5）、把第三大的数字放在倒数第三位上。
         *（6）、把第四大的数字放在倒数第三位上。
         *（7）、把第五大的数字放在倒数第三位上。
         *（8）、观察上面的规律，用双层for循环把数组排序。
         */
        
        
#if 0

        /** (1）、定义一个6个整型的数组，让奇偶位元素的值交换。*/
        int array[6] = {3, 2, 4, 5, 6, 1};
        int temp = 0;
        for (int i = 0; i < 6; i+=2) {
            temp = array[i];
            array[i] = array[i + 1];
            array[i + 1] = temp;
        }
        for (int i = 0; i < 6; i++) {
            printf("%d ", array[i]);
        }
        printf("\n");
        printf("--------------\n");
        
        
        /** （2）、定义一个6个整型的数组，如果奇位比偶位元素的值大，则交换两个数的值。*/
        for (int i = 0; i < 6; i+=2) {
            if (array[i] > array[i + 1]) {
                temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
            }
        }
        for (int i = 0; i < 6; i++) {
            printf("%d ", array[i]);
        }
        printf("\n");
        printf("--------------\n");
#endif
#if 0
        /** 第一次:定义一个6个整型的数组，通过俩俩比较把最大值放在后面，实现最大值放在最后。*/
        int array[6] = {4, 6, 3, 1, 2, 5,};
        int temp = 0;
        for (int i = 0; i < 6 - 1; i++) {    // 第一次,比较五次
            if (array[i] > array[i + 1]) {
                temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
            }
        }
        /** 第二次:在上题的基础上把倒数第二大的数字放在倒数第二位。（别再原来的for循环上操作，新创建一个for循环）*/
        for (int i = 0; i < 6 - 2; i++) {    // 第二次,比较四次
            if (array[i] > array[i + 1]) {
                temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
            }
        }
        /** 第三次:把第三大的数字放在倒数第三位上 */
        for (int i = 0; i < 6 - 3; i++) {    // 第三次,比较三次
            if (array[i] > array[i + 1]) {
                temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
            }
        }
        /** 第四次: 把第四大的数字放在倒数第四位上 */
        for (int i = 1; i < 6 - 4; i++) {     // 第四次,比较两次
            if (array[i] > array[i + 1]) {
                temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
            }
        }
        /** 第五次:把第五大的数字放在倒数第五位上 */
        for (int i = 1; i < 6 - 4; i++) {     // 第五次,比较一次 此时数组排序完毕
            if (array[i] > array[i + 1]) {
                temp = array[i];
                array[i] = array[i + 1];
                array[i + 1] = temp;
            }
        }
#endif
#if 0
        /** BubbleSort 冒泡排序 */
        int array[6] = {3, 6, 2, 1, 5, 4};
        int temp = 0;
        
        /** 外层的for循环控制比较次数 */
        for (int i = 0; i < 6 - 1; i++) {
            
        /** 内层的for循环控制每次的比较 */
            for (int j = 0; j < 6 - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
          
        }
        for (int i= 0; i < 6; i++) {
            printf("%d ", array[i]);
        }
        printf("\n");
#endif
#if 0  /** 无注释版 */
        int array[6] = {3, 2, 1, 5, 6, 4};
        int temp = 0;
        for (int i = 0; i < 6 - 1; i++) {
            for (int j = 0; j < 6 - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < 6; i++) {
            printf("%d ", array[i]);
        }
        printf("\n");
#endif
#if 0
        /** 计算数组元素个数 */
        int array[] = {3, 4, 2, 1};
        
        /** 计算数组的字节数 */
        printf("%lu\n", sizeof(array));
        
        int count1 = sizeof(array) / sizeof(int);
        printf("count1 = %d\n",count1);
        
        
        /** 数组的总字节数除以第一个元素所占的字节数, 就可以得出有几个元素了 */
        int count2 = sizeof(array) / sizeof(array[0]);
        printf("count2 = %d\n", count2);
#endif
#if 0  // 冒泡排序优化版
        int array[6] = {6, 5, 4, 2, 3, 1};
        int count = sizeof(array) / sizeof(array[0]);
        
        int temp = 0;
        int flag = 1;   /**< 1 表示数组无序 */
        for (int i = 0; i < count - 1 && 1 == flag; i++) {
            flag = 0;  /**< 0 表示有序,假设是有序 */
            for (int j = 0; j < count - 1 - i; j++) {
                if (array[j] > array[j + 1]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                    flag = 1;  /**< 发生交换说明是无序,将flag赋值为1 */
                }
            }
        }
        for (int i = 0; i < count; i++) {
            printf("%d ", array[i]);
        }
        printf("\n");
#endif
    }
#pragma mark ** 练习
    {}
#pragma mark - 知识点3 字符数组(字符串)
    {
#if 0
        /**
         * 字符数组是一维数组, 数组元素是字符类型(char)
         *
         */
        /** 定义字符数组 */
        char string[5] = {'a', 'b', 'c', 'd', 'e'};
        
        /** 字符数组所占字节数 */
        printf("%lu\n", sizeof(string));
        
        char string2[10] = {'i', 'O', 'S'};
        printf("%lu\n",sizeof(string2));
        
        /** 注意: 双引号"" 定义的字符数组,在数组的最后一位,系统会自动添加一个\0. 所以整个字符数组占的字节数会多一个字节 */
        char string3[] = "iphone";
        printf("%lu\n", sizeof(string3));
#endif
#if 0
        /** 字符串常用函数 */
        char string4[] = "iphone6Splus";
        
        /** 函数1: strlen(), 计算字符串长度 */
        printf("长度:%lu\n", strlen(string4));
        printf("字节数:%lu\n",sizeof(string4));
#endif
#if 0
        
        /** 函数2: strcpy(), 字符串拷贝 */
        char string1[] = "iphone";
        char string2[100] = "iOS";
        strcpy(string2, string1);
        
        /** %s, 输出字符串,直到遇到\0, 停止输出 */
        printf("%s\n",string1);
        printf("%s\n", string2);
        
        printf("over");
    
#endif
#if 0
        /** 函数3: 拼接strcat */
        char string1[] = "iphone";
        char string2[20] = "iOS";
        strcat(string2, string1);  /**< string1拼接在string2的后面 */
        printf("%s\n", string2);
        printf("%s\n", string1);
#endif
#if 0
        /** 函数4: 字符串比较 strcmp */
        char string1[] = "abc";
        char string2[20] = "arc";
        
        /** 函数有一个返回值,通过返回值判断比较的结果 */
        /** strcmp 是两个字符串从第一个字节开始比较,比较的值为两个字符的ASCII码值之差, 当比较值不为0的时候,停止比较. 根据值的正/负,判断大小 */
        int result = strcmp(string1, string2);
        printf("result:%d\n", result);
    
#endif
    }
#pragma mark ** 练习
    {
        /** 查找字符串中的空个数 */
#if 0
        char string5[] = "I love iOS, i want an iphone6s";
        int count = 0;
        int i = 0;
        while (string5[i] != '\0') {
            if (string5[i] == ' ') {
                count++;
            }
            i++;
        }
        printf("空格数为%d个\n", count);
#endif
        
    
    
    }
#pragma mark - 宏定义
#if 0
    {
        /** 宏定义通常是在函数的外面定义.
         * 详见 main 函数的上面宏部分
         */
        
        printf("%f\n", PI);
        MUL(3, 5);
        printf("%d\n", MUL(3,5));
    
    }
#endif
#pragma mark ** 练习
    return 0;
}
